jsonrpc-derive 18.0.0

High level, typed wrapper for `jsonrpc-core`
Documentation
High level, typed wrapper for `jsonrpc_core`. Enables creation of "Service" objects grouping a set of RPC methods together in a typed manner. Example ``` use jsonrpc_core::{IoHandler, Result, BoxFuture}; use jsonrpc_core::futures::future; use jsonrpc_derive::rpc; #[rpc(server)] pub trait Rpc { #[rpc(name = "protocolVersion")] fn protocol_version(&self) -> Result; #[rpc(name = "add")] fn add(&self, a: u64, b: u64) -> Result; #[rpc(name = "callAsync")] fn call(&self, a: u64) -> BoxFuture>; } struct RpcImpl; impl Rpc for RpcImpl { fn protocol_version(&self) -> Result { Ok("version1".into()) } fn add(&self, a: u64, b: u64) -> Result { Ok(a + b) } fn call(&self, _: u64) -> BoxFuture> { Box::pin(future::ready(Ok("OK".to_owned()).into())) } } fn main() { let mut io = IoHandler::new(); let rpc = RpcImpl; io.extend_with(rpc.to_delegate()); } ``` Pub/Sub Example Each subscription must have `subscribe` and `unsubscribe` methods. They can have any name but must be annotated with `subscribe` or `unsubscribe` and have a matching unique subscription name. ``` use std::sync::{atomic, Arc, RwLock}; use std::collections::HashMap; use jsonrpc_core::{Error, ErrorCode, Result}; use jsonrpc_derive::rpc; use jsonrpc_pubsub::{Session, PubSubHandler, SubscriptionId, typed::{Subscriber, Sink}}; #[rpc] pub trait Rpc { type Metadata; /// Hello subscription #[pubsub( subscription = "hello", subscribe, name = "hello_subscribe", alias("hello_sub") )] fn subscribe(&self, _: Self::Metadata, _: Subscriber, param: u64); /// Unsubscribe from hello subscription. #[pubsub( subscription = "hello", unsubscribe, name = "hello_unsubscribe" )] fn unsubscribe(&self, _: Option, _: SubscriptionId) -> Result; } #[derive(Default)] struct RpcImpl { uid: atomic::AtomicUsize, active: Arc>>>, } impl Rpc for RpcImpl { type Metadata = Arc; fn subscribe(&self, _meta: Self::Metadata, subscriber: Subscriber, param: u64) { if param != 10 { subscriber.reject(Error { code: ErrorCode::InvalidParams, message: "Rejecting subscription - invalid parameters provided.".into(), data: None, }).unwrap(); return; } let id = self.uid.fetch_add(1, atomic::Ordering::SeqCst); let sub_id = SubscriptionId::Number(id as u64); let sink = subscriber.assign_id(sub_id.clone()).unwrap(); self.active.write().unwrap().insert(sub_id, sink); } fn unsubscribe(&self, _meta: Option, id: SubscriptionId) -> Result { let removed = self.active.write().unwrap().remove(&id); if removed.is_some() { Ok(true) } else { Err(Error { code: ErrorCode::InvalidParams, message: "Invalid subscription.".into(), data: None, }) } } } fn main() { let mut io = jsonrpc_core::MetaIoHandler::default(); io.extend_with(RpcImpl::default().to_delegate()); let server_builder = jsonrpc_tcp_server::ServerBuilder::with_meta_extractor( io, |request: &jsonrpc_tcp_server::RequestContext| Arc::new(Session::new(request.sender.clone())) ); let server = server_builder .start(&"127.0.0.1:3030".parse().unwrap()) .expect("Unable to start TCP server"); // The server spawns a separate thread. Dropping the `server` handle causes it to close. // Uncomment the line below to keep the server running in your example. // server.wait(); } ``` Client Example ``` use jsonrpc_core_client::transports::local; use jsonrpc_core::futures::{self, future}; use jsonrpc_core::{IoHandler, Result, BoxFuture}; use jsonrpc_derive::rpc; /// Rpc trait #[rpc] pub trait Rpc { /// Returns a protocol version #[rpc(name = "protocolVersion")] fn protocol_version(&self) -> Result; /// Adds two numbers and returns a result #[rpc(name = "add", alias("callAsyncMetaAlias"))] fn add(&self, a: u64, b: u64) -> Result; /// Performs asynchronous operation #[rpc(name = "callAsync")] fn call(&self, a: u64) -> BoxFuture>; } struct RpcImpl; impl Rpc for RpcImpl { fn protocol_version(&self) -> Result { Ok("version1".into()) } fn add(&self, a: u64, b: u64) -> Result { Ok(a + b) } fn call(&self, _: u64) -> BoxFuture> { Box::pin(future::ready(Ok("OK".to_owned()))) } } fn main() { let exec = futures::executor::ThreadPool::new().unwrap(); exec.spawn_ok(run()) } async fn run() { let mut io = IoHandler::new(); io.extend_with(RpcImpl.to_delegate()); let (client, server) = local::connect::(io); let res = client.add(5, 6).await.unwrap(); println!("5 + 6 = {}", res); server.await.unwrap() } ```